﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////
#include "NewLevelBehaviors.h"
// GBMP Header
#include "GbmpBuiltInParameterDefinitionsNew.h"
#include "GbmpModelViewTypes.h"
#include "GcmpBuiltInParameterDefinitions.h"
#include "ILevelNameManager.h"
#include "LevelUtils.h"
#include "NewLevel.h"
// GCMP Header
#include "AuxiliaryElementUtils.h"
#include "CommandParameters.h"
#include "DbObjectUtils.h"
#include "GbmpInternalCommands.h"
#include "ICalculator.h"
#include "ICalculatorCollection.h"
#include "ICopyStrategyReporter.h"
#include "IDocument.h"
#include "IElementBasicInformation.h"
#include "IElementDeletionContext.h"
#include "IElementModelShape.h"
#include "IElementParameterBindings.h"
#include "IElementParameters.h"
#include "IElementShapeHandle.h"
#include "IElementStatus.h"
#include "IExternalData.h"
#include "IExternalDataComponent.h"
#include "IGenericElement.h"
#include "IGraphicsElementShape.h"
#include "IGraphicsPoint.h"
#include "IModelView.h"
#include "IParameter.h"
#include "IParameterBinding.h"
#include "IParameterDefinitionLibrary.h"
#include "IRegenerator.h"
#include "ParameterProcessType.h"
#include "Vector3dUtils.h"
#include <set>
#include "NdbUpgrade.h"
#include "EnableCompileWarning_The_LAST_IncludeInCpp.h"


using namespace gcmp;

CREATE_DEBUG_MODE_EXPORT(DisplayNewLevelPlaneIn3DView, L"在三维视图中显示新的标高平面", gcmp::DebugModeGroup::DMGT_OTHERS, L"GDMPLab", L"2023-12-20", L"希望在三维视图中显示标高平面时，可以打开此开关");

BEGIN_UPGRADE_CLASS(gcmp, NewLevelViewSpecificShapeComponent, 2)
ADD_OWNERPTR_IDB_PROPERTY(OwnerPtr<IRenderPriorityOffsetProvider>, RenderPriorityOffsetProvider)
END_UPGRADE_CLASS

BEGIN_UPGRADE_CLASS(gcmp, NewLevelViewSpecificShapeComponent, 3)
ADD_OWNERPTR_IDB_PROPERTY(OwnerPtr<IGraphicsNodeVisibilityCustomizer>, GraphicsNodeVisibilityCustomizer)
END_UPGRADE_CLASS

DBOBJECT_DATA_DEFINE(NewLevelViewSpecificShapeComponent)
{
    m_GraphicsNodeVisibilityCustomizer = nullptr;
}

bool NewLevelViewSpecificShapeComponent::IsVisibleInModelView(const IModelView* pModelView) const
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pModelView, L"参数 const IModelView* 为空指针",L"GDMPLab",L"2024-03-30");
    const IElement *pOwnerElement = GetOwnerElement();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pOwnerElement, L"GetOwnerElement() 返回空指针",L"GDMPLab",L"2024-03-30");

    if (pModelView->GetDocument() != pOwnerElement->GetDocument()) // 不是同文档的不可见
    {
        return false;
    }

    const std::wstring& viewType = pModelView->GetUserDataId();
    if (viewType == L"View3DViewType")
    {
        if (DEBUG_MODE(DisplayNewLevelPlaneIn3DView))
            return true;
    }

    const IElementStatus* pStatus = pOwnerElement->GetStatus();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pStatus, L"无法获取状态集",L"GDMPLab",L"2024-03-30");
    return pStatus->IsVisible();
}

bool NewLevelViewSpecificShapeComponent::IsCuttableByModelViewRange(const IModelView* pModelView) const
{
    return false;
}

OwnerPtr<IGraphicsElementShape> NewLevelViewSpecificShapeComponent::CreateViewSpecificElementShape(const IModelView* pModelView) const
{
    DBG_WARN_AND_RETURN_UNLESS(pModelView != nullptr, nullptr, L"pModelView参数不能为空",L"GDMPLab",L"2024-03-30");
    const IGenericElement* pGenericElement = quick_cast<IGenericElement>(GetOwnerElement());
    DBG_WARN_AND_RETURN_UNLESS(pGenericElement != nullptr, nullptr, L"不是一个Level对象",L"GDMPLab",L"2024-03-30");

    if (const NewLevel* pNewLevel = quick_cast<NewLevel>(pGenericElement->GetExternalObject()))
    {
        const std::wstring& viewType = pModelView->GetUserDataId();
        OwnerPtr<IGraphicsElementShape> opGrep;
        Vector3d viewUp = pModelView->GetUpDirection();
        if (DEBUG_MODE(DisplayNewLevelPlaneIn3DView) && (viewType == L"View3DViewType"))
        {
            opGrep = pNewLevel->CreateLevelGrepIn3DView(pModelView);
        }

        if (Vector3dUtils::IsParallel(viewUp, Vector3d::UnitZ, Constants::DOUBLE_EPS))
        {
            opGrep = pNewLevel->CreateLevelGrep(pModelView);
        }

        return TransferOwnership(opGrep);
    }

    // 不创建ModelView专属GRepDBOBJECT_DATA_DEFINE(NewLevelParametersCustomizer)DBOBJECT_DATA_DEFINE(NewLevelParametersCustomizer)
    return nullptr;
}

bool NewLevelViewSpecificShapeComponent::SetOwnerElement(IElement* pOwnerElement)
{
    m_pOwnerElement = pOwnerElement;
    IGraphicsNodeVisibilityCustomizer* pCustomizer = GetGraphicsNodeVisibilityCustomizerFW__().get();
    if (pCustomizer)
    {
        pCustomizer->SetOwnerElement(pOwnerElement);
    }
    return true;
}

IElement* NewLevelViewSpecificShapeComponent::GetOwnerElement()
{
    return m_pOwnerElement;
}

const IElement* NewLevelViewSpecificShapeComponent::GetOwnerElement() const
{
    return  m_pOwnerElement;
}

bool NewLevelViewSpecificShapeComponent::NeedsRecreateViewSpecificElementShape(const IModelView* pModelView, const RecreateShapeInfo& shapeInfo) const
{
    if (shapeInfo.Type == RecreateShapeInfo::ModelViewScaleChanged)
        return true;

    return false;
}

void NewLevelViewSpecificShapeComponent::SetRenderPriorityOffsetProvider(OwnerPtr<IRenderPriorityOffsetProvider> opProvider)
{
    SetRenderPriorityOffsetProvider__(TransferOwnership(opProvider));
}

const IRenderPriorityOffsetProvider* NewLevelViewSpecificShapeComponent::GetRenderPriorityOffsetProvider() const
{
    return GetRenderPriorityOffsetProvider__().get();
}

IRenderPriorityOffsetProvider* NewLevelViewSpecificShapeComponent::GetRenderPriorityOffsetProvider()
{
    return GetRenderPriorityOffsetProviderFW__().get();
}

void NewLevelViewSpecificShapeComponent::SetGraphicsNodeVisibilityCustomizer(OwnerPtr<IGraphicsNodeVisibilityCustomizer> opCustomizer)
{
    if (opCustomizer)
    {
        opCustomizer->SetOwnerElement(GetOwnerElement());
    }
    SetGraphicsNodeVisibilityCustomizer__(TransferOwnership(opCustomizer));
}

const IGraphicsNodeVisibilityCustomizer* NewLevelViewSpecificShapeComponent::GetGraphicsNodeVisibilityCustomizer() const
{
    return GetGraphicsNodeVisibilityCustomizer__().get();
}

IGraphicsNodeVisibilityCustomizer* NewLevelViewSpecificShapeComponent::GetGraphicsNodeVisibilityCustomizer()
{
    return GetGraphicsNodeVisibilityCustomizerFW__().get();
}

//////////////////////////////////////////////////////////
// NewLevel的CustomizableParameter定制行为
DBOBJECT_DATA_DEFINE(NewLevelParametersCustomizer)
{
    SetOwnerElement(nullptr);
}

bool NewLevelParametersCustomizer::SetOwnerElement(IElement* pOwnerElement)
{
    m_pOwnerElement = pOwnerElement;
    return true;
}

IElement* NewLevelParametersCustomizer::GetOwnerElement()
{
    return m_pOwnerElement;
}

const IElement* NewLevelParametersCustomizer::GetOwnerElement() const
{
    return  m_pOwnerElement;
}

NewLevelParametersCustomizer::NewLevelParametersCustomizer(const IElement* pElement)
    :m_pOwnerElement(const_cast<IElement*>(pElement))
{
}

OwnerPtr<IParameter> NewLevelParametersCustomizer::GetNativeParameter(int paramDefId) const
{
    const IGenericElement* pLevelElement = quick_cast<const IGenericElement>(GetOwnerElement());
    DBG_WARN_AND_RETURN_UNLESS(pLevelElement, nullptr, L"pLevelElement为空",L"GDMPLab",L"2024-03-30");

    const ILevel* pLevel = quick_cast<const ILevel>(pLevelElement->GetExternalObject());
    DBG_WARN_AND_RETURN_UNLESS(pLevel, nullptr, L"pLevel为空",L"GDMPLab",L"2024-03-30");

    // 内建参数
    if (paramDefId == PARAMETER_ID(ElementNameBuiltInParameter))
    {
        //OwnerPtr<IParameter> pParam = NEW_AS_OWNER_PTR(Parameter, GetDocument(),
            //ParameterStorageType::String, false, false, true,
            //PARAMETER_UID(ElementNameBuiltInParameter), ParameterProcessType::GeneralInput);
        ParameterAttributes pa = {false, false, true};
        OwnerPtr<IParameter> pParam = IParameter::CreateParameter(GetDocument(), ParameterStorageType::String,
            pa, PARAMETER_UID(ElementNameBuiltInParameter), ParameterProcessType::GeneralInput);
        pParam->SetValueAsString(pLevelElement->GetBasicInformation()->GetName());
        return TransferOwnership(pParam);
    }

    if (paramDefId == PARAMETER_ID(LevelElevationBuiltInParameter))
    {
        //OwnerPtr<Parameter> pParam = NEW_AS_OWNER_PTR(Parameter, GetDocument(),
            //ParameterStorageType::Double, false, false, true, 
            //PARAMETER_UID(LevelElevationBuiltInParameter), ParameterProcessType::GeneralInput);
        ParameterAttributes pa = {false, false, true};
        OwnerPtr<IParameter> pParam = IParameter::CreateParameter(GetDocument(), ParameterStorageType::Double,
            pa, PARAMETER_UID(LevelElevationBuiltInParameter), ParameterProcessType::GeneralInput);
        pParam->SetValueAsDouble(pLevel->GetElevation());
        return TransferOwnership(pParam);
    }

    const ILevelHeaderBehavior* pLevelHeaderBehavior = pLevel->GetLevelHeaderBehavior();
    if (pLevelHeaderBehavior)
    {
        OwnerPtr<IParameter> parameter = pLevelHeaderBehavior->GetNativeParameter(paramDefId);
        if (IParameter::IsValidParameter(parameter))
        {
            return parameter;
        }
    }

    return nullptr;
}

bool NewLevelParametersCustomizer::SetNativeParameter(const IParameter *param, std::wstring* errorMsg)
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(param, L"param is null.",L"GDMPLab",L"2024-03-30");

    if (errorMsg)
    {
        errorMsg->clear();
    }

    IGenericElement* pLevelElement = quick_cast<IGenericElement>(GetOwnerElement());
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pLevelElement, L"pLevelElement为空",L"GDMPLab",L"2024-03-30");

    ILevel* pLevel = quick_cast<ILevel>(pLevelElement->GetExternalObject());
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pLevel, L"pLevel为空",L"GDMPLab",L"2024-03-30");

    if (param->GetParameterDefinitionId() == PARAMETER_ID(LevelElevationBuiltInParameter))
    {
        return pLevel->SetElevation(param->GetValueAsDouble());
    }

    if (param->GetParameterDefinitionId() == PARAMETER_ID(ElementNameBuiltInParameter))
    {
        return pLevelElement->GetBasicInformation()->SetName(param->GetValueAsString());
    }

    ILevelHeaderBehavior* pLevelHeaderBehavior = pLevel->GetLevelHeaderBehavior();
    if (pLevelHeaderBehavior && pLevelHeaderBehavior->SetNativeParameter(param, errorMsg))
    {
        return true;
    }

    return false;
}

void NewLevelParametersCustomizer::ReportParameterDefinitions(std::vector<int>* pParamDefIds) const
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(pParamDefIds != nullptr, L"pParamDefUids为空",L"GDMPLab",L"2024-03-30");

    const IGenericElement* pLevelElement = quick_cast<IGenericElement>(GetOwnerElement());
    DBG_WARN_AND_RETURN_VOID_UNLESS(pLevelElement, L"pLevelElement为空",L"GDMPLab",L"2024-03-30");

    const ILevel* pLevel = quick_cast<ILevel>(pLevelElement->GetExternalObject());
    DBG_WARN_AND_RETURN_VOID_UNLESS(pLevel, L"pLevel为空",L"GDMPLab",L"2024-03-30");

    // 内建参数
    pParamDefIds->push_back(PARAMETER_ID(ElementNameBuiltInParameter));
    pParamDefIds->push_back(PARAMETER_ID(LevelElevationBuiltInParameter));

    // 标头的参数
    const ILevelHeaderBehavior* pLevelHeaderBehavior = pLevel->GetLevelHeaderBehavior();
    if (pLevelHeaderBehavior)
    {
        pLevelHeaderBehavior->ReportParameterDefinitions(pParamDefIds);
    }
}

bool NewLevelParametersCustomizer::IsParameterModifiable(int parameterId) const
{
    return true;
}

IDocument* NewLevelParametersCustomizer::GetDocument() const
{
    if (!m_pOwnerElement)
    {
        return nullptr;
    }
    return m_pOwnerElement->GetDocument();
}

//////////////////////////////////////////////////////////
// NewLevel的ElementUiManipulatorComponent定制组件

DBOBJECT_DATA_DEFINE(NewLevelUiManipulatorComponent)
{
    m_pOwnerElement = nullptr;
}

bool NewLevelUiManipulatorComponent::SetOwnerElement(IElement* pOwnerElement)
{
    m_pOwnerElement = pOwnerElement;
    return true;
}

IElement* NewLevelUiManipulatorComponent::GetOwnerElement()
{
    return m_pOwnerElement;
}

const IElement* NewLevelUiManipulatorComponent::GetOwnerElement() const
{
    return  m_pOwnerElement;
}
//////////////////////////////////////////////////////////
// NewLevel的ElementUiManipulatorComponent定制行为
DBOBJECT_DATA_DEFINE(NewLevelShapeHandleBehavior)
{
}

gcmp::NewLevelShapeHandleBehavior::NewLevelShapeHandleBehavior(IDocument* pDoc, NewLevelShapeElementPosition pt)
    :m_document(pDoc)
    , m_Position(pt)
{

}

gcmp::NewLevelShapeHandleBehavior::~NewLevelShapeHandleBehavior()
{
}

IElementShapeHandle * gcmp::NewLevelShapeHandleBehavior::GetElementShapeHandle() const
{
    IElementShapeHandle* pElement = quick_cast<IElementShapeHandle>(GetDocument()->GetElement(GetElementShapeHandleId()));
    return pElement;
}

DECLARE_CALCULATOR_CREATOR(NewLevelShapeHandlerGRepCalculator);
void gcmp::NewLevelShapeHandleBehavior::GetCalculators(ICalculatorCollection* calculators) const
{
    IElementShapeHandle* pElementShapeHandle = GetElementShapeHandle();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pElementShapeHandle != nullptr, L"pElementShapeHandle指针无效",L"GDMPLab",L"2024-03-30");

    // NewLevelShapeHandlerGRepCalculator 计算器需要触发一次Handle的数据修改，只有数据修改后才会调用函数CreateGrahicsElementShapeInModelView刷新Handle视图显示
    ADD_CALCULATOR(NewLevelShapeHandlerGRepCalculator, pElementShapeHandle->GetDocument(), pElementShapeHandle->GetPositionRdIdForBehavior());
}

gcmp::OwnerPtr<gcmp::IGraphicsElementShape> gcmp::NewLevelShapeHandleBehavior::CreateGrahicsElementShapeInModelView(const gcmp::IModelView * pModelView) const
{
    const std::wstring& viewType = pModelView->GetUserDataId();
    if (viewType != L"ElevationViewType" && viewType != L"SectionViewType")
    {
        return nullptr;
    }

    IElementShapeHandle* pElementShapeHandle = GetElementShapeHandle();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pElementShapeHandle != nullptr, L"pElementShapeHandle指针无效",L"GDMPLab",L"2024-03-30");

    //根据朝右方向向量和标高的数据，计算GRep
    Vector3d elevInsRightDir = pModelView->GetRightDirection();
    IGenericElement* pGenericElement = quick_cast<IGenericElement>(GetDocument()->GetElement(pElementShapeHandle->GetMasterId()));
    if (pGenericElement == nullptr)
    {
        return nullptr;
    }

    NewLevel* pLevel = quick_cast<NewLevel>(pGenericElement->GetExternalObject());
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pLevel, L"pLevel指针无效",L"GDMPLab",L"2024-03-30");

    Vector3d startPnt, endPnt;
    pLevel->GetModelViewProjectLine(pModelView, startPnt, endPnt);

    OwnerPtr<IGraphicsElementShape> opReturnGrep = gcmp::IGraphicsElementShape::Create(GraphicsRenderLayer::TransientObject);
    OwnerPtr<IGraphicsPoint> opGPoint = IGraphicsPoint::Create();
    Vector3d point = GetPosition() == NewLevelShapeElementPosition::Left ? startPnt : endPnt;
    opGPoint->SetPoint(point);
    opReturnGrep->AddChild(TransferOwnership(opGPoint));

    return TransferOwnership(opReturnGrep);
}

bool gcmp::NewLevelShapeHandleBehavior::GetHandleCommandString(const IObject* commandEnvironment, std::wstring & commandStr, gcmp::CommandParameters& cmdParams) const
{
    IElementShapeHandle* pElementShapeHandle = GetElementShapeHandle();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pElementShapeHandle != nullptr, L"pElementShapeHandle指针无效",L"GDMPLab",L"2024-03-30");

    commandStr = ID_CMD_MOVE_LEVEL_SHAPE_HANDLE;
    cmdParams.clear();
    cmdParams[L"ElementId"] = pElementShapeHandle->GetElementId().AsInt64();

    return true;
}

void gcmp::NewLevelShapeHandleBehavior::UpdatePositionIndexInMasterElement()
{
    IElementShapeHandle* pElementShapeHandle = GetElementShapeHandle();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pElementShapeHandle != nullptr, L"pElementShapeHandle指针无效",L"GDMPLab",L"2024-03-30");

    static int i = 0; // TODO, 临时在这里用静态变量表示，后面需要放到关联更新框架中去。
    pElementShapeHandle->SetPositionIndexInMasterElement(i++);
    pElementShapeHandle->GetDocument()->GetRegenerator()->MarkRegenDataId(pElementShapeHandle->GetShapeHandlePositionIndexInMasterElementRdId());

}

//////////////////////////////////////////////////////////
// NewLevel的ElementDeletionComponent定制行为
DBOBJECT_DATA_DEFINE(NewLevelDeletionComponent)
{
    m_pOwnerElement = nullptr;
}

bool NewLevelDeletionComponent::SetOwnerElement(IElement* pOwnerElement)
{
    m_pOwnerElement = pOwnerElement;
    return true;
}

IElement* NewLevelDeletionComponent::GetOwnerElement()
{
    return m_pOwnerElement;
}

const IElement* NewLevelDeletionComponent::GetOwnerElement() const
{
    return  m_pOwnerElement;
}

bool NewLevelDeletionComponent::CanBeDeleted(const IElementDeletionContext* pDeleteContext, std::wstring* explanation) const
{
    const IGenericElement* pGenericElement = quick_cast<const IGenericElement>(GetOwnerElement());
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pGenericElement, L"pGenericElement指针无效",L"GDMPLab",L"2024-03-30");

    const ILevel* pLevel = quick_cast<ILevel>(pGenericElement->GetExternalObject());
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pLevel, L"pLevel指针无效",L"GDMPLab",L"2024-03-30");

    const IElementStatus* pStatus = pGenericElement->GetStatus();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pStatus, L"pStatus指针无效",L"GDMPLab",L"2024-03-30");

    // 不属于任何单体的标高可以删除
    ElementId buildingId = pLevel->GetBuildingId();
    if (buildingId.IsValid() == false)
    {
        return pStatus->CanBeDeleted();
    }
    
    std::vector<const ILevel*> levels = LevelUtils::GetStoreyLevelsInBuilding(pGenericElement->GetDocument(), buildingId);
    
    // 如果单体中只有一个要删除的标高， 则不删除
    if (levels.size() == 1)
    {
        return false;
    }

    // 如果删除环境不存在， 默认可以删除
    if (pDeleteContext == nullptr)
    {
        return pStatus->CanBeDeleted();
    }

    // 如果单体内的所有Level都在待删除的列表里面， 则不能删除
    bool canBeDeleted = false;
    const std::set<ElementId>& elementIdsToDeleted = pDeleteContext->GetElementIdsToDelete();
    FOR_EACH(pLevel, levels)
    {
        if (elementIdsToDeleted.find(pLevel->GetOwnerElement()->GetElementId()) == elementIdsToDeleted.end())
        {
            canBeDeleted = pStatus->CanBeDeleted();
            break;
        }
    }

    if (canBeDeleted && explanation != nullptr)
    {
        *explanation = GBMP_TR(L"每个单体至少保留一个楼层，如需删除，请至楼层管理中删除单体！");
    }

    return canBeDeleted;
}

bool NewLevelDeletionComponent::GetDeletionWarning(std::vector<std::wstring>& strWarning) const
{
    std::wstring explanation;
    if (CanBeDeleted(nullptr,&explanation) == false)
    {
        strWarning.push_back(explanation);
        return true;
    }

    const IGenericElement* pGenericElement = quick_cast<const IGenericElement>(GetOwnerElement());
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pGenericElement, L"pGenericElement指针无效",L"GDMPLab",L"2024-03-30");

    const ILevel* pLevel = quick_cast<ILevel>(pGenericElement->GetExternalObject());
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pLevel, L"pLevel指针无效",L"GDMPLab",L"2024-03-30");

    strWarning.clear();

    FOR_EACH(viewId, pLevel->GetAssociatedCeilingViewIds())
    {
        IModelView* pCeilingModelView = quick_cast<IModelView>(GetOwnerElement()->GetDocument()->GetElement(viewId));
        if (pCeilingModelView != nullptr)
        {
            std::wstring viewTypeName = GbmpModelViewTypeUtil::GetModelViewTypeName(pCeilingModelView->GetUserDataId());
            strWarning.push_back(viewTypeName + L" - " + pCeilingModelView->GetBasicInformation()->GetName());
        }
    }
    FOR_EACH(viewId, pLevel->GetAssociatedPlanViewIds())
    {
        IModelView* pPlaneModelView = quick_cast<IModelView>(GetOwnerElement()->GetDocument()->GetElement(viewId));
        if (pPlaneModelView != nullptr)
        {
            std::wstring viewTypeName = GbmpModelViewTypeUtil::GetModelViewTypeName(pPlaneModelView->GetUserDataId());
            strWarning.push_back(viewTypeName + L" - " + pPlaneModelView->GetBasicInformation()->GetName());
        }
    }
    return true;
}

//////////////////////////////////////////////////////////
// NewLevel的NewLevelTransformationComponent定制行为

DBOBJECT_DATA_DEFINE(NewLevelTransformationComponent)
{
    m_pOwnerElement = nullptr;
}

bool NewLevelTransformationComponent::SetOwnerElement(IElement* pOwnerElement)
{
    m_pOwnerElement = pOwnerElement;
    return true;
}

IElement* NewLevelTransformationComponent::GetOwnerElement()
{
    return m_pOwnerElement;
}

const IElement* NewLevelTransformationComponent::GetOwnerElement() const
{
    return  m_pOwnerElement;
}

bool NewLevelTransformationComponent::Translate(const IElementMoveContext& moveContext)
{
    IGenericElement* pGenericElement = quick_cast<IGenericElement>(GetOwnerElement());
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pGenericElement, L"pGenericElement指针无效",L"GDMPLab",L"2024-03-30");

    NewLevel* pNewLevel = quick_cast<NewLevel>(pGenericElement->GetExternalObject());
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pNewLevel, L"pNewLevel指针无效",L"GDMPLab",L"2024-03-30");

    return pNewLevel->Translate(moveContext);
}

bool NewLevelTransformationComponent::Rotate(const Vector3d& origin, const Vector3d& axis, double angle)
{
    return false;
}

bool NewLevelTransformationComponent::Transform(const Matrix4d& matrix)
{
    return false;
}

bool NewLevelTransformationComponent::CanBeMoved(std::wstring* explanation) const
{
    const IElement* pElement = GetOwnerElement();
    if (pElement == nullptr)
        return true;

    return pElement->GetStatus()->CanBeMoved();
}

bool NewLevelTransformationComponent::CanBeRotated(std::wstring* explanation) const
{
    return false;
}


//////////////////////////////////////////////////////////
// NewLevel的NewLevelCopyPasteComponent定制行为
DBOBJECT_DATA_DEFINE(NewLevelCopyPasteComponent)
{
    m_pOwnerElement = nullptr;
}
void gcmp::NewLevelCopyPasteComponent::UpdateAfterCopy(const ICopyContext& copyContext)
{
    IDocument* pDoc = GetDocument();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDoc, L"pGrenericElement为空，不合法",L"GDMPLab",L"2024-03-30");
    DBG_WARN_AND_RETURN_VOID_UNLESS(m_pOwnerElement, L"m_pOwnerElement为空，不合法",L"GDMPLab",L"2024-03-30");

    IGenericElement* pGrenericElement = quick_cast<IGenericElement>(pDoc->GetElement(m_pOwnerElement->GetElementId()));
    DBG_WARN_AND_RETURN_VOID_UNLESS(pGrenericElement, L"pGrenericElement为空，不合法",L"GDMPLab",L"2024-03-30");

    NewLevel* pLevel = quick_cast<NewLevel>(pGrenericElement->GetExternalObject());
    DBG_WARN_AND_RETURN_VOID_UNLESS(pLevel, L"pGrid为空，不合法",L"GDMPLab",L"2024-03-30");

    ILevelNameManager* pLevelNameManager = ILevelNameManager::Get(pDoc);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pLevelNameManager, L"pGrid为空，不合法",L"GDMPLab",L"2024-03-30");

    pGrenericElement->GetBasicInformation()->SetName(LevelUtils::GetNextLevelName(pDoc, pLevel->GetBuildingId()).ToString());
}

bool gcmp::NewLevelCopyPasteComponent::CanBeCopied(std::wstring * pErrorMessage) const
{
    const IElement * pIElement = GetOwnerElement();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pIElement, L"获取IElement指针失败",L"GDMPLab",L"2024-03-30");
    if (const IExternalDataComponent * pExternalDataComponent = pIElement->GetExternalDataComponent())
    {
        const std::vector<OwnerPtr<IExternalData>>& externalDatas = pExternalDataComponent->GetAllExternalDatas();
        FOR_EACH(externalData, externalDatas)
        {
            if (!externalData)
            {
                continue;
            }
            std::wstring explanationString;
            if (!externalData->CanBeCopied(&explanationString))
            {
                SAFE_INIT_POINTER(pErrorMessage, explanationString);
                return false;
            }
        }
    }
    return true;
}

bool gcmp::NewLevelCopyPasteComponent::IsStrongParentsNeedCopied() const
{
    const IElement * pIElement = GetOwnerElement();;
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pIElement, L"获取IElement指针失败",L"GDMPLab",L"2024-03-30");
    if (const IExternalDataComponent * pExternalDataComponent = pIElement->GetExternalDataComponent())
    {
        const std::vector<OwnerPtr<IExternalData>>& externalDatas = pExternalDataComponent->GetAllExternalDatas();
        FOR_EACH(externalData, externalDatas)
        {
            if (!externalData)
            {
                continue;
            }
            if (externalData->IsStrongParentsNeedCopied())
            {
                return true;
            }
        }
    }
    return false;
}

bool gcmp::NewLevelCopyPasteComponent::ShouldBeCopiedTogether(const ICopyContext & copyContext) const
{
    const IElement * pIElement = GetOwnerElement();;
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pIElement, L"获取IElement指针失败",L"GDMPLab",L"2024-03-30");
    if (const IExternalDataComponent * pExternalDataComponent = pIElement->GetExternalDataComponent())
    {
        const std::vector<OwnerPtr<IExternalData>>& externalDatas = pExternalDataComponent->GetAllExternalDatas();
        FOR_EACH(externalData, externalDatas)
        {
            if (!externalData)
            {
                continue;
            }
            if (!externalData->ShouldBeCopiedTogether(copyContext))
            {
                return false;
            }
        }
    }
    return true;
}

void gcmp::NewLevelCopyPasteComponent::UpdateForWeakParentCopied(const IDocument * pDocFrom, const IElement * pSource, const IElement * pCopy) const
{
    const IElement * pIElement = GetOwnerElement();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pIElement, L"获取IElement指针失败",L"GDMPLab",L"2024-03-30");
    if (const IExternalDataComponent * pExternalDataComponent = pIElement->GetExternalDataComponent())
    {
        const std::vector<OwnerPtr<IExternalData>>& externalDatas = pExternalDataComponent->GetAllExternalDatas();
        FOR_EACH(externalData, externalDatas)
        {
            if (!externalData)
            {
                continue;
            }
            externalData->UpdateForWeakParentCopied(pDocFrom, pSource, pCopy);
        }
    }
}

IDocument * gcmp::NewLevelCopyPasteComponent::GetDocument() const
{
    if (!m_pOwnerElement)
    {
        return nullptr;
    }
    return m_pOwnerElement->GetDocument();
}

ElementId gcmp::NewLevelCopyPasteComponent::GetOwnerElementId() const
{
    if (!m_pOwnerElement)
    {
        return ElementId::InvalidID;
    }
    return m_pOwnerElement->GetElementId();
}

DBOBJECT_DATA_DEFINE(NewLevelCopyStrategyComponent) {
    m_pOwnerElement = nullptr;
}

void gcmp::NewLevelCopyStrategyComponent::Report(const gcmp::ICopyContext & copyContext, gcmp::ICopyStrategyReporter& reporter) const
{
    IDocument* pDoc = GetDocument();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDoc, L"pGrenericElement为空，不合法",L"GDMPLab",L"2024-03-30");

    IGenericElement* pGrenericElement = quick_cast<IGenericElement>(pDoc->GetElement(m_pOwnerElement->GetElementId()));
    DBG_WARN_AND_RETURN_VOID_UNLESS(pGrenericElement, L"pGrenericElement为空，不合法",L"GDMPLab",L"2024-03-30");

    NewLevel* pLevel = quick_cast<NewLevel>(pGrenericElement->GetExternalObject());
    DBG_WARN_AND_RETURN_VOID_UNLESS(pLevel, L"pGrid为空，不合法",L"GDMPLab",L"2024-03-30");

    const IElementParameterBindings* pBehavior = pGrenericElement->GetElementParameters()->GetElementParameterBindings();
    if (pBehavior)
    {
        const std::vector<OwnerPtr<IParameterBinding>>& bindingInfos = pBehavior->GetParameterBindings();
        FOR_EACH(binding, bindingInfos)
        {
            reporter.ReportToKeep(binding->GetSourceElementId());
        }
    }

    reporter.ReportToKeep(pGrenericElement->GetBasicInformation()->GetTypeId());

    const IGraphicsElementShape * pGrep = pGrenericElement->GetElementModelShape()->GetGraphicsElementShape();
    if (pGrep)
    {
        std::set<ElementId> idTokeep;
        pGrep->Report(idTokeep);
        ICopyStrategyReporterUtils::ReportToKeep(reporter, idTokeep.begin(), idTokeep.end());
    }

    if (const IExternalDataComponent* pExternalDataComponent = pGrenericElement->GetExternalDataComponent())
    {
        const std::vector<OwnerPtr<IExternalData>>& externalDatas = pExternalDataComponent->GetAllExternalDatas();
        FOR_EACH(externalData, externalDatas)
        {
            if (!externalData)
            {
                continue;
            }
            externalData->Report(copyContext, reporter);
        }
    }

    reporter.ReportToKeep(pLevel->GetBuildingId());

    FOR_EACH(iter, pLevel->GetAssociatedPlanViewIds())
    {
        reporter.ReportToDiscard(iter);
    }
    FOR_EACH(iter, pLevel->GetAssociatedCeilingViewIds())
    {
        reporter.ReportToDiscard(iter);
    }
}

IDocument * gcmp::NewLevelCopyStrategyComponent::GetDocument() const
{
    if (!m_pOwnerElement)
    {
        return nullptr;
    }
    return m_pOwnerElement->GetDocument();
}

ElementId gcmp::NewLevelCopyStrategyComponent::GetOwnerElementId() const
{
    if (!m_pOwnerElement)
    {
        return ElementId::InvalidID;
    }
    return m_pOwnerElement->GetElementId();
}
